package org.x.mybatis.config;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.x.common.base.util.UserContextHolder;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Configuration
@MapperScan({"org.x.*.mapper","org.x.service.module.*.mapper"})
public class MybatisPlusConfig {

    // 租户字段配置
    private static final String TENANT_COLUMN = "tenant_id";
    // 需要忽略多租户过滤的表
    private static final List<String> IGNORE_TABLES = Arrays.asList(
            "sys_tenants","sys_tenants_ds", "sys_tokens",
            "sys_menu_closure","sys_menus","sys_dept_closure","sys_ds_config","sys_perm",
            "sys_role_perm","sys_user_dept","sys_user_roles","exam_paper_question");

    /**
     * 多租户插件配置
     */
    @Bean
    public TenantLineInnerInterceptor tenantLineInnerInterceptor() {
        TenantLineInnerInterceptor interceptor = new TenantLineInnerInterceptor();
        interceptor.setTenantLineHandler(new TenantLineHandler() {
            // 当前租户ID值获取（从ThreadLocal中获取）
            @Override
            public StringValue getTenantId() {
                String currentTenantId = getCustomTenantId();
                if (currentTenantId != null) {
                    return new StringValue(currentTenantId);
                }
                return null;
            }
            // 租户字段名
            @Override
            public String getTenantIdColumn() {
                return TENANT_COLUMN;
            }

            // 表过滤
            @Override
            public boolean ignoreTable(String tableName) {
                return IGNORE_TABLES.contains(tableName.toLowerCase());
            }
        });
        return interceptor;
    }

    private String getCustomTenantId() {
        String currentTenantId = UserContextHolder.getCurrentTenantId();
        if (currentTenantId != null) {
            return currentTenantId;
        }
        return  UserContextHolder.getTenantId();
    }

    /**
     * 自动填充字段处理器
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MetaObjectHandler() {
            @Override
            public void insertFill(MetaObject metaObject) {
                this.strictInsertFill(metaObject, "createBy", String.class, StpUtil.getLoginIdAsString());
                this.strictInsertFill(metaObject, "createId", String.class, StpUtil.getLoginIdAsString());
                this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
                this.strictInsertFill(metaObject, "tenantId",String.class, getCustomTenantId());

//                this.strictUpdateFill(metaObject, "updateBy", String.class, UserContextHolder.getCurrentUserId());
//                this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
            }

            @Override
            public void updateFill(MetaObject metaObject) {
                this.strictUpdateFill(metaObject, "updateBy", String.class,  StpUtil.getLoginIdAsString());
                this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
            }
        };
    }

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(tenantLineInnerInterceptor());
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}